package admin;

import java.sql.SQLException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Vector;

import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;

import utils.Utils;

import model.ListRooms;
import model.Room;


/**
 * <p>Title: RoomModel </p>
 *
 * <p>
 * 	Description: Cette classe est le model d'une javax.swing.JTable, elle sert a peupler la liste (JTable)
 *  de salle de jeu.
 * </p>
 *
 * <p>Copyright: (c) 2008 FSSIM</p>
 *
 * <p>Company: FSSImock</p>
 *
 * @author Antoine Farnault
 * @author Aubry Pirian
 * @version 2.0
 */
public class RoomModel extends AbstractTableModel implements TableModel{

	private static final long serialVersionUID = 1L;
	private JTable tableData;
	Vector<Object> rowData = new Vector<Object>();	// Une ligne de la table
	
	private Vector<String> newRow = new Vector<String>();
	private int maxId;
	
	private static final int ID_COL = 0;			// Colonne du numéro
	private static final int ADDRESS_COL = 1;		// Colonne de l'adresse
	private static final int NAME_COL = 2;			// Colonne du nom
	private static final int STATUS_COL = 3;		// Colonne du statut
	private static final int CONNECTIONS_COL = 4;	// Colonne des connexions
	
	private static final Integer[] DELETERS = {ID_COL};		// colonnes permettant l'effacement
	private static final String DELETE_CODE = "delete";		// mot clé d'effacement

	
	/**
	 * Remplissage du modèle de ligne d'insertion
	 */
	private void initNewBlankRow() {
		this.newRow.add("Nouvelle salle :");
		this.newRow.add("----");
		this.newRow.add("Veuillez entrer le nouveau nom");
		this.newRow.add("----");
		this.newRow.add("----");
	}
	
	
	/**
	 * Constructeur
	 */
	public RoomModel() {
		super();
		this.maxId = -1;
		try {
			ListRooms ls = new ListRooms();
			ls.connect();
			LinkedList<Room> salles = ls.getSalles();
			Iterator<Room> iterator = salles.iterator();
			while (iterator.hasNext()) {
				Room r = iterator.next();
				if (r.getId()>this.maxId) this.maxId=r.getId();
				rowData.add(r);
			}
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		this.initNewBlankRow();
		this.newBlankRow();
	}

	
	/**
	 * Sauve la JTable parente
	 * @param jt : JTable parente
	 */
	public void setJTable (JTable jt) {
		this.tableData = jt;
	}
	
	
	/**
	 * Redefinition de la methode getColumnName de AbstractTableModel
	 * Elle donne automatiquement les noms des colonnes
	 * @param column le numero de colonne dont il faut le nom
	 * @return column le nom de la colonne
	 */
	@Override
	 public  String getColumnName(int column) {
         if (column == ID_COL) return "N°";
         if (column == ADDRESS_COL) return "Adresse";
         if (column == NAME_COL) return "Nom";
         if (column == STATUS_COL) return "Statut";
         if (column == CONNECTIONS_COL) return "Connexions";
         return "";
	 }
	
	
	/**
	 * Redefinition de la methode getColumnCount de AbstractTableModel
	 * Elle donne le nombre de colonnes de la table
	 * @return le nombre de colonne
	 */
	@Override
	public int getColumnCount() {
		return 5;
	}
	
	
	/**
	 * redefinition de la methode getRowCount de AbstractTableModel
	 * Elle donne automatiquement le nombre de lignes de la table
	 * @return le nombre de lignes
	 */
	@Override
	public int getRowCount() {
		return rowData.size();
	}
	
	
	/**
	 * redefinition de la methode getValueAt de AbstractTableModel
	 * Elle donne la valeur d'une cellule de la table
	 * @param i le numero de ligne
	 * @param j le numero de la colonne
	 * @return l'objet a la ligne i et colonne j
	 */
	@Override
	public Object getValueAt(int i, int j) {
//		if (i==0) return newRow.get(j);
		Object o = rowData.get(i);
		if (o instanceof Vector) {
			// 1e ligne (nouvelle salle)
			return newRow.get(j);
		}
		if (o instanceof Room) {
			Room r = (Room) o;
			if (j == ID_COL) {	// Id
				int v = r.getId();
				if (v==-1) return "";
				else return v;
			}
			if (j == ADDRESS_COL) {	// Address
				return r.getAddress();
			}
			if (j == NAME_COL) {	// Name
				return r.getName();
			}
			if (j == STATUS_COL) {	// Status
				return r.getStatus();
			}
			if (j == CONNECTIONS_COL) {	// Connections
				try {
					return r.getConnections();
				} catch (NoSuchFieldException e) {
					System.out.println("Paramètre non valide.");
				} catch (SQLException e) {
					System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getMessage());
				} catch (ClassNotFoundException e) {
					System.out.println("Impossible de se connecter à la base de données (driver JDBC non disponible)");
				}
			}
		}
		return "Error";
	}
	
	
	/**
	 * Redefinition de la méthode setValueAt de AbstractTableModel
	 * Elle enregistre la valeur entrée
	 * @param o objet à enregistrer
	 * @param i le numero de ligne
	 * @param j le numero de la colonne
	 */
	@Override
	public void setValueAt(Object o, int i, int j) {
		if (i==0) {
			this.saveNewRow(o);
			return;
		}
		String s = (String) o;
		if ( Utils.inArray( DELETERS, j) && s.equalsIgnoreCase(DELETE_CODE) ) {
			this.deleteRow(i);
			return;
		}
		Room r = (Room) this.rowData.get(i);
		if (j==ID_COL) {	// Id
			if (!s.equals("#")) {
				//TODO : vérifier que s est libre, sinon si s<maxId ===> décaller les suivants
				try {
					r.setId(Integer.parseInt(s));
				} catch (NumberFormatException e) {
					System.out.println("Le numero doit être un entier");
					e.printStackTrace();
				} catch (SQLException e) {
					System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getSQLState());
					e.printStackTrace();
				} catch (NoSuchFieldException e) {
					System.out.println("Attribut non valide");
					e.printStackTrace();
				}
			}
			return;
		}
		if (j==ADDRESS_COL) {	// Address
			try {
				r.setAddress(s);
			} catch (NoSuchFieldException e) {
				System.out.println("Attribut non valide");
				e.printStackTrace();
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getMessage());
				e.printStackTrace();
			}
			return;
		}
		if (j==NAME_COL) {	// Name
			try {
				r.setName(s);
			} catch (NoSuchFieldException e) {
				System.out.println("Attribut non valide");
				e.printStackTrace();
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getMessage());
				e.printStackTrace();
			}
			return;
		}
		if (j==STATUS_COL) {	// Status
			try {
				r.setStatus(s);
			} catch (NoSuchFieldException e) {
				System.out.println("Attribut non valide");
				e.printStackTrace();
			} catch (SQLException e) {
				System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getMessage());
				e.printStackTrace();
			}
			return;
		}
		
	}

	
	/**
	 * Ajout d'une ligne dans la table
	 * @param o	: objet à sauver
	 */
	public void saveNewRow(Object o) {
		String s = (String) o;
//		Vector<String> row = (Vector<String>) this.rowData.get(0);
		Room r;
		try {
			r = new Room();
			r.create(s);
			System.out.println("Ajout à la liste...");
			this.rowData.remove(0);
			this.rowData.add(r);
			// Création d'une nouvelle ligne
			this.newBlankRow();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		this.tableData.updateUI();
    }
	
	
	/**
	 * Crée une nouvelle ligne vide en position 0
	 */
	private void newBlankRow() {
		this.rowData.add(0,this.newRow);
	}
	
	
	/**
	 * Supprime la ligne i
	 * @param i ligne à supprimer
	 */
	public void deleteRow (int i) {
		Room r = (Room) this.rowData.get(i);
		try {
			r.delete();
			this.rowData.remove(i);
		} catch (NoSuchFieldException e) {
			System.out.println("Paramètre invalide.");
		} catch (SQLException e) {
			System.out.println("Erreur SQL n°"+e.getErrorCode()+": "+e.getMessage());
		}
		this.tableData.updateUI();
	}
	
	
	/**
	 * Indique si une case est éditable
	 * @param row		: ligne de la case
	 * @param column	: colonne de la case
	 */
	@Override
	public boolean isCellEditable(int row, int column){
		if (row==0) {
			if (column!=NAME_COL) return false;
		}
		if (column==CONNECTIONS_COL) return false;
		return true;
	}
	
	
}
